#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef struct _node
{
    int data;
    struct _node *prev, *next;
}singleNode, *myNode;

typedef struct _list
{
    int len;
    struct _node *head, *tail;
}singleList, *myList;

/*
 * 初始化的行为
 * 链表：头部尾部都初始化为空 长度初始化为0
 */
myList initList()
{
    myList list = (myList)malloc(sizeof(singleList));
    if(list == NULL)
    {
        printf("Error: Apply memory failed. Unable to initialize list.\n");
        return NULL;
    }
    list->head = NULL;
    list->tail = NULL;
    list->len = 0;
    return list;
}

/*
 * 从头部insert时的行为
 * 新节点：前标为空 后标设为之前的链表头部节点 数据设为新数据
 * 之前的链表头部节点：前标更新为新节点 后标和数据不动
 * 链表：头部更新为新节点 尾部原则上不动(除非尾部为空 即链表本来为空) 长度+1
 */
void insertHead(myList list, int data)
{
    myNode new = (myNode)malloc(sizeof(singleNode));
    if(new == NULL)
    {
        printf("Error: Apply memory failed. Unable to insert before head.\n");
        return ;
    }
    new->data = data;
    new->next = NULL;
    new->prev = NULL;
    if (list->head != NULL) //如果链表头部不为空
    {
        new->next = list->head;
        list->head->prev = new; //将链表头部的前标改为新节点
    }
    list->head = new;
    if (list->len == 0) //如果链表为空
    {
        list->tail = new; //将链表尾部也改为新节点
    }
    list->len++;
    return ;
}

/*
 * 从头部delete时的行为
 * 目前的链表头部节点：取出数据 释放内存空间
 * 之后的链表头部节点：前标更新为空 后标和数据不动
 * 链表：头部更新为新的链表头部节点 尾部原则上不动(除非尾部为空 即链表本来为空) 长度-1
 */
void deleteHead(myList list)
{
    if (list->head == NULL) //如果链表为空
    {
        printf("Error: List is empty. Unable to delete head.\n");
        return ;
    }
    if (list->head->next != NULL) //如果链表不止一个元素
    {
        list->head = list->head->next;
        free(list->head->prev);
        list->head->prev = NULL;
    }
    else //如果链表只有一个元素
    {
        free(list->head);
        list->head = NULL;
        list->tail = NULL;
    }
    list->len--;
    return ;
}

/*
 * 从尾部insert时的行为
 * 新节点：前标为之前的链表尾部节点 后标为空 数据设为新数据
 * 之前的链表尾部节点：后标更新为新节点 前标和数据不动
 * 链表：尾部更新为新节点 头部原则上不动(除非头部为空 即链表本来为空) 长度+1
 */
void insertTail(myList list, int data)
{
    myNode new = (myNode)malloc(sizeof(singleNode));
    if(new == NULL)
    {
        printf("Error: Apply memory failed. Unable to insert after tail.\n");
        return ;
    }
    new->data = data;
    new->next = NULL;
    new->prev = NULL;
    if (list->tail != NULL) //如果链表头部不为空
    {
        new->prev = list->tail;
        list->tail->next = new; //将链表头部的前标改为新节点
    }
    list->tail = new;
    if (list->len == 0) //如果链表为空
    {
        list->head = new; //将链表尾部也改为新节点
    }
    list->len++;
    return ;
}

/*
 * 从尾部delete时的行为
 * 目前的链表尾部节点：取出数据 释放内存空间
 * 之后的链表尾部节点：后标更新为空 前标和数据不动
 * 链表：尾部更新为新的链表尾部节点 尾部原则上不动(除非尾部为空 即链表本来为空) 长度-1
 */
void deleteTail(myList list)
{
    if (list->tail == NULL) //如果链表为空
    {
        printf("Error: List is empty. Unable to delete tail.\n");
        return ;
    }
    if (list->tail->prev != NULL) //如果链表不止一个元素
    {
        list->tail = list->tail->prev;
        free(list->tail->next);
        list->tail->next = NULL;
    }
    else //如果链表只有一个元素
    {
        free(list->tail);
        list->head = NULL;
        list->tail = NULL;
    }
    list->len--;
    return ;
}

void print_r(myList list)
{
    printf("    *****************************\n");
    printf("    *   length  = %d\n", list->len);
    int i = 0;
    myNode index = list->head;
    while(1)
    {
        if (index == NULL)
        {
            break;
        }
        printf("    *   list[%d] : %d\n", i, index->data);
        index = index->next;
        i++;
    }
}

 int main(void)
 {
    int i;
    myList list = initList();
    printf("Initializing Program Success.\nList addr: %p\n\n", list);
    while(1)
    {
        printf("----------------------------------------\n");
        printf("    *   Input(Only Number): ");
        scanf("%d", &i);
        if(i == 0)
            return 0;
        else if(i > 0)
        {
            insertHead(list, i); //链表头插入
            //insertTail(list, i); //链表尾插入
            print_r(list);
        }
        else if(i < 0)
        {
            deleteHead(list); //链表头删除
            //deleteTail(list);   //链表尾删除
            print_r(list);
        }
    }
    free(list);
    return 0;
 }
